package src; 

import java.awt.Color;
import java.util.*;

/**
 * Keeps record of 9 SubGrids, checks if the game has been won. Also houses placePiece method, which is used by Players for 
 * modifying the grid. 
 * @author Akshat
 */
public class Board 
{
	private SubGrid[][] board;
	private boolean hasWinner; 

	public Board()
	{
		board = new SubGrid[3][3]; 
		initBoard();
	}
	
	/**
	 * Initializes SubGrid[][] with nine empty SubGrids, which represent TicTacToe boards
	 */
	public void initBoard()
	{
		for( int i = 0; i < board.length; i++)
		{
			for( int j = 0; j < board[i].length; j++ )
			{
				board[i][j] = new SubGrid(i,j);
			}
		}
	}
	
	/**
	 * If at least one of the SubGrids can still be played on, returns true. Otherwise, returns false. 
	 * @return whether or not Grid is still playable
	 */
	public boolean canPlay()
	{
		if( !hasWinner )
		{
			for( int i = 0; i < board.length; i++)
			{
				for( int j = 0; j < board[i].length; j++ )
				{
					if( board[i][j].canPlay() )
					{
						return true; 
					}
				}
			}
		}
		
		return false; 
	}
	
	
	/**
	 * Checks if board is eligible to play on (not winner or tie). Check if location is valid. If so, puts piece on board.
	 * @param piece to be placed
	 * @param loc where to be placed
	 * @return whether or not piece was placed.
	 */
	public boolean placePiece(GamePiece piece, GridLocation loc)
	{		
		SubGrid grid = get(loc.getMainRow(), loc.getMainCol());
		
		if( grid.canPlay() && grid.getOpenLocations().contains(loc) )
		{
			grid.set(loc.getSubRow(), loc.getSubCol(), piece);; 
			grid.checkForWinner(); 
			return true;
		}
		
		return false; 
	}
	
	/**
	 * To be called after a move has been made. Checks to see if game has been won. 
	 * @return whether game has been won or not
	 */
	public boolean checkForWinner()
	{
		boolean winner = false; 
		Color color; 
		
		//first check if won rows
		for( int i = 0; i < board.length; i++ )
		{
			winner = true; 
			
			if( board[i][0].hasWinner() )
			{
				color = board[i][0].getWinnerColor(); 
				
				for( int j = 1; j < board[i].length; j++)
				{
					if( board[i][j].hasWinner() )
					{
						if(!color.equals(board[i][j].getWinnerColor()))
						{
							winner = false; 
							break; 
						}
					}
					else
					{
						winner = false; 
					}
				}
				
				if( winner )
				{
					hasWinner = true; 
					return true; 
				}
			}
			else
			{
				winner = false; 
			}
		}
		
		//next check columns
		for( int j = 0; j < board[0].length; j++ )
		{
			winner = true; 
			
			if( board[0][j].hasWinner() )
			{
				color = board[0][j].getWinnerColor(); 
				
				for( int i = 1; i < board.length; i++)
				{
					if( board[i][j].hasWinner() )
					{
						if(!color.equals(board[i][j].getWinnerColor()))
						{
							winner = false; 
							break; 
						}
					}
					else
					{
						winner = false; 
					}
				}
				
				if( winner )
				{
					hasWinner = true; 
					return true;
				}
			}
			else
			{
				winner = false; 
			}
		}
		
		//check diagonal top-bottom left-right
		if( board[0][0].hasWinner() )
		{
			color = board[0][0].getWinnerColor(); 
			winner = true; 
			int row = 1; 
			int col = 1; 
			
			while( row < board.length && col < board[row].length  )
			{
				if( board[row][col].hasWinner() && color.equals(board[row][col].getWinnerColor()))
				{
					row++;
					col++;
					winner = true; 
				}
				else
				{
					winner = false; 
					break; 
				}
			}
			
			if( winner )
			{
				hasWinner = true; 
				return true; 
			}
		}
		
		//check diagonal bottom-top left-right
		if( board[board.length-1][0].hasWinner() )
		{
			color = board[board.length - 1][0].getWinnerColor(); 
			winner = true; 
			
			int row = board.length - 2; 
			int col = 1; 
			
			while( row >= 0 && col < board[row].length  )
			{
				if( board[row][col].hasWinner() && color.equals(board[row][col].getWinnerColor()))
				{
					row--;
					col++;
					winner = true; 
				}
				else
				{
					winner = false; 
					break; 
				}
			}
			
			if( winner )
			{
				hasWinner = true; 
				return true; 
			}
		}
		
		return false; 
	}

	
	
	/**
	 * If game is won, colors entire board color of winner. 
	 * @param c Color of winner
	 */
	public void celebrate(Color c)
	{
		System.out.println("winner");
		
		for( int i = 0; i < board.length; i++ )
		{
			for( int j = 0; j < board[i].length; j++ )
			{
				board[i][j].colorBoard(c);
			}
		}
	}
	
	/**
	 * Returns all the empty spaces on the grid
	 * @return a list of all open locations (to be used in AI)
	 */
	public ArrayList<GridLocation> getAllOpenLocations()
	{
	    ArrayList<GridLocation> openLoc = new ArrayList<GridLocation>();
	    for(int i = 0; i< board.length; i++)
	    {
	        for(int j = 0; j< board[i].length; j++)
	        {
	            ArrayList<GridLocation> temp = board[i][j].getOpenLocations();
	            
	            if( temp.size() != 0)
	            {
	                for( GridLocation l : temp)
	                {
	                    openLoc.add(l); 
	                }
	            }
	        }
	    }
	    return openLoc;
	}
	
	/**
	 * Returns SubGrid at location in subGrid[][]
	 * @param row row
	 * @param col column
	 * @return SubGrid
	 */
	public SubGrid get(int row, int col)
	{
		return board[row][col]; 
	}

}
